iT邦幫忙

DAY 20
1

無痛學習SpringMVC與Spring Security系列 第 20

[Security]Spring設定需認證的URL以及自訂login表單

  • 分享至 

  • xImage
  •  

昨天漏提及自Spring Security 3.2.x開始新支援Cross Site Request Forgery(CSRF) Protection,若使用Java Config,@EnableWebSecurity預設啟動CSRF,但若用XML組態檔要手動宣告<crsf />於tag中,基本上就是在login以及logout的網頁中插入隱藏input,相關參數使用CSRF預設值即可,如下,

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />

另外從Spring Security的官方文件有提到,Spring Filter Chain的執行是有順序的,從昨天console log可以看出來,

00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 1 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 2 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 3 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 4 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 5 of 14 in additional filter chain; firing Filter: 'LogoutFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 6 of 14 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 7 of 14 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 8 of 14 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 9 of 14 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 10 of 14 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 11 of 14 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
00:07:43 [http-nio-8080-exec-2] AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 12 of 14 in additional filter chain; firing Filter: 'SessionManagementFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 13 of 14 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
00:07:43 [http-nio-8080-exec-2] FilterChainProxy - / at position 14 of 14 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
00:07:43 [http-nio-8080-exec-2] FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /; Attributes: [authenticated]
00:07:43 [http-nio-8080-exec-2] ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
00:09:55 [http-nio-8080-exec-5] FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fec65191: Principal: org.springframework.security.core.userdetails.User@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@166c8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: C66D8794777A252AB6FC2D3182AB2A54; Granted Authorities: ROLE_ADMIN, ROLE_USER
00:09:55 [http-nio-8080-exec-5] AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@282b221e, returned: 1
00:09:55 [http-nio-8080-exec-5] FilterSecurityInterceptor - Authorization successful
00:09:55 [http-nio-8080-exec-5] FilterSecurityInterceptor - RunAsManager did not change Authentication object
00:09:55 [http-nio-8080-exec-5] FilterChainProxy - / reached end of additional filter chain; proceeding with original chain

在使用者未login成功前,對於URL的任何request,都會經過14個filter的檢查,基本上若任何一個filter丟出exception,則意味使用者未通過認證,當輸入正確username及password後,則UsernamePasswordAuthenticationFilter則會將認證過使用者的相關屬性放入Spring SecurityContextHolder,Spring Security ContextHolder存放已認證過使用者的Authentication物件,供網頁存取用。

00:09:55 [http-nio-8080-exec-4] UsernamePasswordAuthenticationFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fec65191: Principal: org.springframework.security.core.userdetails.User@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@166c8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: C66D8794777A252AB6FC2D3182AB2A54; Granted Authorities: ROLE_ADMIN, ROLE_USER
00:09:55 [http-nio-8080-exec-4] SavedRequestAwareAuthenticationSuccessHandler - Redirecting to DefaultSavedRequest Url: http://localhost:8080/SpringMVC/
00:09:55 [http-nio-8080-exec-4] DefaultRedirectStrategy - Redirecting to 'http://localhost:8080/SpringMVC/'

今天接著介紹如何設定需認證的URL以及自訂login表單,同樣是設定HttpSecurity物件,故要更新SecurityConfig如下:

@EnableWebSecurity //Enable springFliterChain
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// TODO Auto-generated method stub
		http.
			authorizeRequests()
				.antMatchers("/resources/**").permitAll() //resource資料夾靜態資料可匿名存取
				.antMatchers("/dcn") //對象為所有網址
				.authenticated() //存取必須通過驗證
			.and()
			.formLogin() 
				.loginPage("/login") //則產生自訂login表單
				.failureUrl("/login?error") //如果認證失敗,則導往/login並帶參數error
				.defaultSuccessUrl("/dcn") //認證通過後導往的Url
				.permitAll()
			.and()
			.logout()
				.logoutSuccessUrl("/login?logout") //
			    .permitAll();
	}
	

我們拿掉anyReqest(),改用antMatchers()方法來指定需要認證的URL,如果是permitAll()則代表可以匿名存取,網站的靜態資料如css檔, image檔等都應設定可匿名存取。

新增login.jsp,code如下:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>




<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Page</title>


<div class="grid">
	<div class="row">
			<div class="span1"></div>
			<div class="span5">
				<c:if test="{not empty error}">
					 <div class="balloon bottom">
                        <div class="padding20">
                            ${error}
                        </div>
                    </div>
				</c:if>
				<c:if test="{not empty msg}">
					 <div class="balloon bottom">
                        <div class="padding20">
                            ${msg}
                        </div>
                    </div>
				</c:if>
				<c:url value="/login" var="loginUrl"/>
				<form action="/${loginUrl}" method="POST">
					<label for="username">Username</label>
					<div class="input-control text">
						<input type="text" value="" placeholder="input username" 
						id="username" name="username"/>
						<button class="btn-clear"></button>
					</div> 
					<label for="password">Password</label>
					<div class="input-control password">
						<input type="password" value="" placeholder="input password"
						id="password" name="password"/>
						<button class="btn-reveal"></button>
					</div>
					<input type="submit" value="Submit"/>
					<input type="hidden" name="${_csrf.parameterName}"
		             value="${_csrf.token}" />
				</form>
			</div>
		</div>
</div>

啟動Server,則可以開到初始畫面如下

存取DCN List則需登入


上一篇
[Security]Spring Security簡介與第一個login畫面
下一篇
[Security]利用Spring Security Tag搭配JSTL有條件顯示網頁資訊
系列文
無痛學習SpringMVC與Spring Security31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言